package com.vf.admin.client.controller.pay.sandpay.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>Title : </p>
 * <p>Description : </p>
 * <p>DevelopTools : IDEA</p>
 * <p>DevelopSystem : Windows10</p>
 *
 * @Author : NemoMeng
 * @Date 2023/7/3 11:50
 */
public class RSAUtil {


    private static final ConcurrentHashMap<String, PrivateKey> PRIVATE_KEYS = new ConcurrentHashMap<>();
    private static final String PRIVATE_KEY = "PRIVATE_KEY";

    static {
        //以下三种方式选择一种即可
        //方式一：私钥字符串
        //initPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCOakpB7iff5gW9bAUnWAyuiWzjWUPOihYyzU/iaeT5V5fHqM0ynwLrmkc0afIZumkqFZA7YAEGHsu/cAGrWthymHUehwrkTNMBIKUEUjOOR6hrupZtDi7m1uXolMnd2ZRExQQqJS6lTc5xDSxMdeHnnu9fQ7nfvoY6eJGi/pG6rqWcO8pTqgQtj3PudU/31TR3Q+OgB3c8wMGfxBPGfx7PX7YFpVTeVUbz6SFiPZm+moepF3okonNpWYgBGEvJmGsUJFqesZLYyj0ZmBJWQEqgI5+l3Cs9TxpOZ2eIiWcURP5IDHmd1Xwoj8GUm256tgoVBKmNwwjqoonob5Wx6vNVAgMBAAECggEADBUIZ7+EsoIZSpC3fzcBHG2cR01zazpb18ODW3oQavb7cXzoq7rBzKsyD0hNudEOyvs5WVAzxgkmz/74pUj3xAEbLpPWYLgDzryuQ0eWCCQcLceOq4HgiMUCjFDTL3ceFReB2vF8m5mWQhEUCQiXOcdKF5LvWgQX7y37bRCb3HKDRr0b2PQDHG9AoTFqSa/miFhbpSbHEAg9naHdNj+UMLVup8H9KMcxFlP/amQpHMDAuJLLwP/9sydbu4exOZtg0dj+TJB0mb89gKIwA1mEcDS5L7wOvYy0Ae+xCYAPb02m89XsOw/T8yLX6UeIwSd5qDR2/Nm2b96IEgMzr4uTAQKBgQD0W7fSiWnjaMYXF2XLamaNqFHnm9MiCUOwBFZ1b5NdSGRSkxEz+VJJ7qYStEoTiSQnNk0+acJni5mCePs7mMLIwIA2lNmS5uX7DZEbS1dBDtDocRCwYKjPT/9Fxe9Z7MAUvuT0ED4MvNJ91CKO+oPlCWEkUujrL33jPF8rHqmYmQKBgQCVMzzCGdHOPSBtZSXTmpeHHo8VjAMmG5QDtTx/ZLKM1zThLsX/P2yeGgYEElhKIGF/VA4tjt6iAZ1yzBmHeY4QOKsh8NqGSh4fbacqWyOdMd5BIWZBU3dw/vkffsaT/4Dw1Yu1ZISx9HN0jUw1qXCiTC+HYSCv5CtIuBGgmHI6HQKBgCU36xG4OFaY2MMfnzOSazhcUM1UIJ5ohtTCdGDCs9Fbe1xQZihiazQzkzv6FeZP1x/Z134QIbofuyvyPWHgbJqjJ2Qo29LSNGk+scFUgl+4X/1na0FSF6Qr7Re1hDVQKBmA0eKSrsDF6dGcg/7/DSPPf+pGbo+T1jrMMTqiGvbRAoGAcjF1H1qDqkY+u3vfJ8X6lABfoy42esRA1VWxqA96WTGd13vlLydsCtYAJL2ltZZzCPFcqKHg5D44M9Ti9T2j7eZxlNizaHTx+TwD5fc7muTAJzlY+kbX9DQymFh/xGaaWboX5A27QjjG5T4ARlIZUx7cgdFlIzqPpmi7lR8YzkECgYAO5HVX2xQOqhg2lIBI9jTGDPZl1HCji+0LBWINsIp7NQ7o/BsMXK8Q/GP8Yfd2ymv9Vj86TDfS7zzKOD9mVyBH8nqnIL8sQWkF6a31MEjZ/nL1buuCgeLKYKmXKlARBPn3dqfRKz9OWLQ2R0DR8D/nnJz/c2JF05rwiEbPCG+7Lg==");
        //方式二：私钥classpath路径
        initPrivateKey("classpath:cert/112233.pfx", "112233");
//        initPrivateKey("src/main/resources/112233.pfx", "112233");
        //方式三：私钥绝对路径
        //测试
//        initPrivateKey("D:/sandopay/68888TS121677.pfx", "123456");
        //正式
//        initPrivateKey("D:/sandopay/112233.pfx", "112233");
    }

    public static PrivateKey getPrivateKey() {

        return PRIVATE_KEYS.get(PRIVATE_KEY);
    }

    public static String getSignContent(Map<String, String> params) {
        StringBuilder content = new StringBuilder();
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (key != null && !key.isEmpty() && value != null && !value.isEmpty()) {
                content.append(i == 0 ? "" : "&").append(key).append("=").append(value);
            }
        }
        return content.toString();
    }

    public static String sign(String content, PrivateKey privateKey) {
        try {
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initSign(privateKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void initPrivateKey(String privateKeyStr) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            PRIVATE_KEYS.put(PRIVATE_KEY, privateKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void initPrivateKey(String privateKeyPath, String password) {
        System.out.println("路径："+privateKeyPath);
        String classpathKey = "classpath:";
        InputStream inputStream = null;
        try {
            if (privateKeyPath.startsWith(classpathKey)) {
                inputStream = RSAUtil.class.getClassLoader().getResourceAsStream(privateKeyPath.substring(classpathKey.length()));
            } else {
                inputStream = Files.newInputStream(Paths.get(privateKeyPath));
            }

            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            char[] pwdChar;
            if (password == null || password.trim().equals("")) {
                pwdChar = null;
            } else {
                pwdChar = password.toCharArray();
            }
            keyStore.load(inputStream, pwdChar);

            Enumeration<String> aliases = keyStore.aliases();
            String alias = null;
            if (aliases.hasMoreElements()) {
                alias = aliases.nextElement();
            }
            PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, pwdChar);
            PRIVATE_KEYS.put(PRIVATE_KEY, privateKey);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("私钥不存在");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("算法不存在");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignored) {
                }
            }
        }
    }
}
